home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / WINGs / wbutton.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-06  |  17.8 KB  |  830 lines

  1.  
  2.  
  3.  
  4.  
  5. #include "WINGsP.h"
  6.  
  7. typedef struct W_Button {
  8.     W_Class widgetClass;
  9.     WMView *view;
  10.  
  11.     char *caption;
  12.     
  13.     char *altCaption;
  14.     
  15.     WMFont *font;
  16.  
  17.     WMColor *textColor;
  18.     WMColor *altTextColor;
  19.     WMColor *disTextColor;
  20.  
  21.     W_Pixmap *image;
  22.     W_Pixmap *altImage;
  23.  
  24.     W_Pixmap *dimage;
  25.  
  26.     void *clientData;
  27.     WMAction *action;
  28.  
  29.     int tag;
  30.     
  31.     int groupIndex;
  32.     
  33.     float periodicDelay;
  34.     float periodicInterval;
  35.     
  36.     WMHandlerID *timer;               /* for continuous mode */
  37.     
  38.     struct {
  39.     WMButtonType type:4;
  40.     WMImagePosition imagePosition:4;
  41.     WMAlignment alignment:2;
  42.  
  43.     unsigned int selected:1;
  44.     
  45.     unsigned int enabled:1;
  46.  
  47.     unsigned int bordered:1;
  48.  
  49.     unsigned int springLoaded:1;
  50.     
  51.     unsigned int pushIn:1;           /* change relief while pushed */
  52.     
  53.     unsigned int pushLight:1;      /* highlight while pushed */
  54.     
  55.     unsigned int pushChange:1;     /* change caption while pushed */
  56.         
  57.     unsigned int stateLight:1;     /* state indicated by highlight */
  58.     
  59.     unsigned int stateChange:1;    /* state indicated by caption change */
  60.  
  61.     unsigned int statePush:1;      /* state indicated by relief */
  62.  
  63.     unsigned int continuous:1;     /* continually perform action */
  64.     /* */
  65.     unsigned int prevSelected:1;
  66.  
  67.     unsigned int pushed:1;
  68.     
  69.     unsigned int wasPushed:1;
  70.  
  71.     unsigned int redrawPending:1;
  72.     
  73.     unsigned int addedObserver:1;
  74.     } flags;
  75. } Button;
  76.  
  77.  
  78.  
  79. #define DEFAULT_BUTTON_WIDTH    60
  80. #define DEFAULT_BUTTON_HEIGHT    24
  81. #define DEFAULT_BUTTON_ALIGNMENT    WACenter
  82. #define DEFAULT_BUTTON_IS_BORDERED    True
  83.  
  84.  
  85. #define DEFAULT_RADIO_WIDTH    100
  86. #define DEFAULT_RADIO_HEIGHT    20
  87. #define DEFAULT_RADIO_ALIGNMENT    WALeft
  88. #define DEFAULT_RADIO_IMAGE_POSITION    WIPLeft
  89. #define DEFAULT_RADIO_TEXT    "Radio"
  90.  
  91.  
  92. #define DEFAULT_SWITCH_WIDTH    100
  93. #define DEFAULT_SWITCH_HEIGHT    20
  94. #define DEFAULT_SWITCH_ALIGNMENT    WALeft
  95. #define DEFAULT_SWITCH_IMAGE_POSITION    WIPLeft
  96. #define DEFAULT_SWITCH_TEXT    "Switch"
  97.  
  98.  
  99. static void destroyButton(Button *bPtr);
  100. static void paintButton(Button *bPtr);
  101.  
  102. static void handleEvents(XEvent *event, void *data);
  103. static void handleActionEvents(XEvent *event, void *data);
  104.  
  105.  
  106. static char *WMPushedRadioNotification="WMPushedRadioNotification";
  107.  
  108.  
  109. #define NFONT(b) (b)->view->screen->normalFont
  110.  
  111.  
  112. WMButton*
  113. WMCreateCustomButton(WMWidget *parent, int behaviourMask)
  114. {
  115.     Button *bPtr;
  116.     
  117.     bPtr = wmalloc(sizeof(Button));
  118.     memset(bPtr, 0, sizeof(Button));
  119.  
  120.     bPtr->widgetClass = WC_Button;
  121.     
  122.     bPtr->view = W_CreateView(W_VIEW(parent));
  123.     if (!bPtr->view) {
  124.     wfree(bPtr);
  125.     return NULL;
  126.     }
  127.     bPtr->view->self = bPtr;
  128.  
  129.     bPtr->flags.type = 0;
  130.  
  131.     bPtr->flags.springLoaded = (behaviourMask & WBBSpringLoadedMask)!=0;
  132.     bPtr->flags.pushIn = (behaviourMask & WBBPushInMask)!=0;
  133.     bPtr->flags.pushChange = (behaviourMask & WBBPushChangeMask)!=0;
  134.     bPtr->flags.pushLight = (behaviourMask & WBBPushLightMask)!=0;
  135.     bPtr->flags.stateLight = (behaviourMask & WBBStateLightMask)!=0;
  136.     bPtr->flags.stateChange = (behaviourMask & WBBStateChangeMask)!=0;
  137.     bPtr->flags.statePush = (behaviourMask & WBBStatePushMask)!=0;
  138.     
  139.     W_ResizeView(bPtr->view, DEFAULT_BUTTON_WIDTH, DEFAULT_BUTTON_HEIGHT);
  140.     bPtr->flags.alignment = DEFAULT_BUTTON_ALIGNMENT;
  141.     bPtr->flags.bordered = DEFAULT_BUTTON_IS_BORDERED;
  142.     
  143.     bPtr->flags.enabled = 1;
  144.  
  145.  
  146.     WMCreateEventHandler(bPtr->view, ExposureMask|StructureNotifyMask,
  147.              handleEvents, bPtr);
  148.  
  149.     WMCreateEventHandler(bPtr->view, ButtonPressMask|ButtonReleaseMask
  150.              |EnterWindowMask|LeaveWindowMask, 
  151.              handleActionEvents, bPtr);
  152.  
  153.     W_ResizeView(bPtr->view, DEFAULT_BUTTON_WIDTH, DEFAULT_BUTTON_HEIGHT);
  154.     bPtr->flags.alignment = DEFAULT_BUTTON_ALIGNMENT;
  155.     bPtr->flags.bordered = DEFAULT_BUTTON_IS_BORDERED;
  156.  
  157.     return bPtr;
  158. }
  159.  
  160.  
  161.  
  162. WMButton*
  163. WMCreateButton(WMWidget *parent, WMButtonType type)
  164. {
  165.     W_Screen *scrPtr = W_VIEW(parent)->screen;
  166.     Button *bPtr;
  167.     
  168.     switch (type) {
  169.      case WBTMomentaryPush:
  170.     bPtr = WMCreateCustomButton(parent, WBBSpringLoadedMask
  171.                     |WBBPushInMask|WBBPushLightMask);
  172.     break;
  173.  
  174.      case WBTMomentaryChange:
  175.     bPtr = WMCreateCustomButton(parent, WBBSpringLoadedMask
  176.                     |WBBPushChangeMask);
  177.     break;
  178.         
  179.      case WBTPushOnPushOff:
  180.     bPtr = WMCreateCustomButton(parent, WBBPushInMask|WBBStatePushMask
  181.                     |WBBStateLightMask);
  182.     break;
  183.     
  184.      case WBTToggle:
  185.     bPtr = WMCreateCustomButton(parent, WBBPushInMask|WBBStateChangeMask
  186.                     |WBBStatePushMask);
  187.     break;
  188.  
  189.      case WBTOnOff:
  190.     bPtr = WMCreateCustomButton(parent, WBBStateLightMask);
  191.     break;
  192.  
  193.      case WBTSwitch:
  194.     bPtr = WMCreateCustomButton(parent, WBBStateChangeMask);
  195.     bPtr->flags.bordered = 0;
  196.     bPtr->image = WMRetainPixmap(scrPtr->checkButtonImageOff);
  197.     bPtr->altImage = WMRetainPixmap(scrPtr->checkButtonImageOn);
  198.     break;
  199.  
  200.      case WBTRadio:
  201.     bPtr = WMCreateCustomButton(parent, WBBStateChangeMask);
  202.     bPtr->flags.bordered = 0;
  203.     bPtr->image = WMRetainPixmap(scrPtr->radioButtonImageOff);
  204.     bPtr->altImage = WMRetainPixmap(scrPtr->radioButtonImageOn);
  205.     break;
  206.  
  207.      default:
  208.      case WBTMomentaryLight:
  209.     bPtr = WMCreateCustomButton(parent, WBBSpringLoadedMask
  210.                     |WBBPushLightMask);
  211.     bPtr->flags.bordered = 1;
  212.     break;
  213.     }
  214.     
  215.     bPtr->flags.type = type;
  216.  
  217.     if (type==WBTRadio) {
  218.     W_ResizeView(bPtr->view, DEFAULT_RADIO_WIDTH, DEFAULT_RADIO_HEIGHT);
  219.     WMSetButtonText(bPtr, DEFAULT_RADIO_TEXT);
  220.     bPtr->flags.alignment = DEFAULT_RADIO_ALIGNMENT;
  221.     bPtr->flags.imagePosition = DEFAULT_RADIO_IMAGE_POSITION;
  222.     } else if (type==WBTSwitch) {
  223.     W_ResizeView(bPtr->view, DEFAULT_SWITCH_WIDTH, DEFAULT_SWITCH_HEIGHT);
  224.     WMSetButtonText(bPtr, DEFAULT_SWITCH_TEXT);
  225.     bPtr->flags.alignment = DEFAULT_SWITCH_ALIGNMENT;
  226.     bPtr->flags.imagePosition = DEFAULT_SWITCH_IMAGE_POSITION;
  227.     }
  228.     
  229.     return bPtr;
  230. }
  231.  
  232.  
  233. static void
  234. updateDisabledMask(WMButton *bPtr)
  235. {
  236.     WMScreen *scr = WMWidgetScreen(bPtr);
  237.     Display *dpy = scr->display;
  238.  
  239.     if (bPtr->image) {
  240.     XGCValues gcv;
  241.  
  242.     bPtr->dimage->mask = XCreatePixmap(dpy, scr->stipple,
  243.                        bPtr->dimage->width, 
  244.                        bPtr->dimage->height, 1);
  245.  
  246.     XSetForeground(dpy, scr->monoGC, 0);
  247.     XFillRectangle(dpy, bPtr->dimage->mask, scr->monoGC, 0, 0,
  248.                bPtr->dimage->width, bPtr->dimage->height);
  249.  
  250.     gcv.foreground = 1;
  251.     gcv.background = 0;
  252.     gcv.stipple = scr->stipple;
  253.     gcv.fill_style = FillStippled;
  254.     gcv.clip_mask = bPtr->image->mask;
  255.     gcv.clip_x_origin = 0;
  256.     gcv.clip_y_origin = 0;
  257.     
  258.     XChangeGC(dpy, scr->monoGC, GCForeground|GCBackground|GCStipple
  259.           |GCFillStyle|GCClipMask|GCClipXOrigin|GCClipYOrigin, &gcv);
  260.  
  261.     XFillRectangle(dpy, bPtr->dimage->mask, scr->monoGC, 0, 0,
  262.                bPtr->dimage->width, bPtr->dimage->height);
  263.  
  264.     gcv.fill_style = FillSolid;
  265.     gcv.clip_mask = None;
  266.     XChangeGC(dpy, scr->monoGC, GCFillStyle|GCClipMask, &gcv);
  267.     }
  268. }
  269.  
  270. void
  271. WMSetButtonImageDefault(WMButton *bPtr)
  272. {
  273.     WMSetButtonImage (bPtr, WMWidgetScreen(bPtr)->buttonArrow);
  274.     WMSetButtonAltImage (bPtr, WMWidgetScreen(bPtr)->pushedButtonArrow);
  275. }
  276.  
  277. void
  278. WMSetButtonImage(WMButton *bPtr, WMPixmap *image)
  279. {
  280.     if (bPtr->image!=NULL)
  281.     WMReleasePixmap(bPtr->image);
  282.     bPtr->image = WMRetainPixmap(image);
  283.  
  284.     if (bPtr->dimage) {
  285.     bPtr->dimage->pixmap = None;
  286.     WMReleasePixmap(bPtr->dimage);
  287.     bPtr->dimage = NULL;
  288.     }
  289.  
  290.     if (image) {
  291.     bPtr->dimage = WMCreatePixmapFromXPixmaps(WMWidgetScreen(bPtr), 
  292.                           image->pixmap, None,
  293.                           image->width, image->height,
  294.                           image->depth);
  295.     updateDisabledMask(bPtr);
  296.     }
  297.  
  298.     if (bPtr->view->flags.realized) {
  299.     paintButton(bPtr);
  300.     }
  301. }
  302.  
  303.  
  304. void
  305. WMSetButtonAltImage(WMButton *bPtr, WMPixmap *image)
  306. {
  307.     if (bPtr->altImage!=NULL)
  308.     WMReleasePixmap(bPtr->altImage);
  309.     bPtr->altImage = WMRetainPixmap(image);
  310.     
  311.     
  312.     if (bPtr->view->flags.realized) {
  313.     paintButton(bPtr);
  314.     }
  315. }
  316.  
  317.  
  318. void
  319. WMSetButtonImagePosition(WMButton *bPtr, WMImagePosition position)
  320. {
  321.     bPtr->flags.imagePosition = position;
  322.     
  323.     
  324.     if (bPtr->view->flags.realized) {
  325.     paintButton(bPtr);
  326.     }
  327. }
  328.  
  329.  
  330.  
  331.  
  332. void
  333. WMSetButtonTextAlignment(WMButton *bPtr, WMAlignment alignment)
  334. {
  335.     bPtr->flags.alignment = alignment;
  336.     
  337.     
  338.     if (bPtr->view->flags.realized) {
  339.     paintButton(bPtr);
  340.     }
  341. }
  342.  
  343. void
  344. WMSetButtonText(WMButton *bPtr, char *text)
  345. {
  346.     if (bPtr->caption)
  347.     wfree(bPtr->caption);
  348.  
  349.     if (text!=NULL) {
  350.     bPtr->caption = wstrdup(text);
  351.     } else {
  352.     bPtr->caption = NULL;
  353.     }
  354.     
  355.     
  356.     if (bPtr->view->flags.realized) {
  357.     paintButton(bPtr);
  358.     }
  359. }
  360.  
  361.  
  362. void
  363. WMSetButtonAltText(WMButton *bPtr, char *text)
  364. {
  365.     if (bPtr->altCaption)
  366.     wfree(bPtr->altCaption);
  367.     
  368.     if (text!=NULL) {
  369.     bPtr->altCaption = wstrdup(text);
  370.     } else {
  371.     bPtr->altCaption = NULL;
  372.     }
  373.     
  374.     if (bPtr->view->flags.realized) {
  375.     paintButton(bPtr);
  376.     }
  377. }
  378.  
  379.  
  380. void
  381. WMSetButtonTextColor(WMButton *bPtr, WMColor *color)
  382. {
  383.     if (bPtr->textColor)
  384.     WMReleaseColor(bPtr->textColor);
  385.  
  386.     bPtr->textColor = WMRetainColor(color);
  387. }
  388.  
  389.  
  390. void
  391. WMSetButtonAltTextColor(WMButton *bPtr, WMColor *color)
  392. {
  393.     if (bPtr->altTextColor)
  394.     WMReleaseColor(bPtr->altTextColor);
  395.  
  396.     bPtr->altTextColor = WMRetainColor(color);
  397. }
  398.  
  399.  
  400. void
  401. WMSetButtonDisabledTextColor(WMButton *bPtr, WMColor *color)
  402. {
  403.     if (bPtr->disTextColor)
  404.     WMReleaseColor(bPtr->disTextColor);
  405.  
  406.     bPtr->disTextColor = WMRetainColor(color);
  407. }
  408.  
  409.  
  410. void
  411. WMSetButtonSelected(WMButton *bPtr, int isSelected)
  412. {
  413.     bPtr->flags.selected = isSelected;
  414.  
  415.     WMPostNotificationName(WMPushedRadioNotification, bPtr, NULL);
  416.     
  417.     if (bPtr->view->flags.realized) {
  418.     paintButton(bPtr);
  419.     }
  420. }
  421.  
  422.  
  423. int
  424. WMGetButtonSelected(WMButton *bPtr)
  425. {
  426.     CHECK_CLASS(bPtr, WC_Button);
  427.     
  428.     return bPtr->flags.selected;
  429. }
  430.  
  431.  
  432. void
  433. WMSetButtonBordered(WMButton *bPtr, int isBordered)
  434. {
  435.     bPtr->flags.bordered = isBordered;
  436.     
  437.     if (bPtr->view->flags.realized) {
  438.     paintButton(bPtr);
  439.     }
  440. }
  441.  
  442.  
  443. void
  444. WMSetButtonFont(WMButton *bPtr, WMFont *font)
  445. {
  446.     if (bPtr->font)
  447.     WMReleaseFont(bPtr->font);
  448.  
  449.     bPtr->font = WMRetainFont(font);
  450. }
  451.  
  452.  
  453. void
  454. WMSetButtonEnabled(WMButton *bPtr, Bool flag)
  455. {
  456.     bPtr->flags.enabled = flag;
  457.  
  458.     if (bPtr->view->flags.mapped) {
  459.     paintButton(bPtr);
  460.     }
  461. }
  462.  
  463.  
  464. void
  465. WMSetButtonTag(WMButton *bPtr, int tag)
  466. {
  467.     bPtr->tag = tag;
  468. }
  469.  
  470.     
  471.  
  472. void
  473. WMPerformButtonClick(WMButton *bPtr)
  474. {
  475.     CHECK_CLASS(bPtr, WC_Button);
  476.   
  477.     if (!bPtr->flags.enabled)
  478.     return;
  479.  
  480.     bPtr->flags.pushed = 1;
  481.     bPtr->flags.selected = 1;
  482.     
  483.     if (bPtr->view->flags.mapped) {
  484.     paintButton(bPtr);
  485.     XFlush(WMScreenDisplay(WMWidgetScreen(bPtr)));
  486.     wusleep(20000);
  487.     }
  488.   
  489.     if (bPtr->groupIndex>0) {
  490.     WMPostNotificationName(WMPushedRadioNotification, bPtr, NULL);
  491.     }
  492.  
  493.     if (bPtr->action)
  494.     (*bPtr->action)(bPtr, bPtr->clientData);
  495.      
  496.     bPtr->flags.pushed = 0;
  497.     
  498.     if (bPtr->view->flags.mapped)
  499.     paintButton(bPtr);
  500. }
  501.  
  502.  
  503.  
  504. void
  505. WMSetButtonAction(WMButton *bPtr, WMAction *action, void *clientData)
  506. {
  507.     CHECK_CLASS(bPtr, WC_Button);
  508.     
  509.     bPtr->action = action;
  510.     
  511.     bPtr->clientData = clientData;
  512. }
  513.  
  514.  
  515.  
  516.  
  517. static void
  518. radioPushObserver(void *observerData, WMNotification *notification)
  519. {
  520.     WMButton *bPtr = (WMButton*)observerData;
  521.     WMButton *pushedButton = (WMButton*)WMGetNotificationObject(notification);
  522.  
  523.     if (bPtr!=pushedButton && pushedButton->groupIndex == bPtr->groupIndex
  524.     && bPtr->groupIndex!=0) {
  525.     if (bPtr->flags.selected) {
  526.         bPtr->flags.selected = 0;
  527.         paintButton(bPtr);
  528.     }
  529.     }
  530. }
  531.  
  532.  
  533.  
  534. void
  535. WMGroupButtons(WMButton *bPtr, WMButton *newMember)
  536. {
  537.     static int tagIndex = 0;
  538.     
  539.     CHECK_CLASS(bPtr, WC_Button);
  540.     CHECK_CLASS(newMember, WC_Button);
  541.  
  542.     if (!bPtr->flags.addedObserver) {
  543.     WMAddNotificationObserver(radioPushObserver, bPtr,
  544.                   WMPushedRadioNotification, NULL);
  545.     bPtr->flags.addedObserver = 1;
  546.     }
  547.     if (!newMember->flags.addedObserver) {
  548.     WMAddNotificationObserver(radioPushObserver, newMember,
  549.                   WMPushedRadioNotification, NULL);
  550.     newMember->flags.addedObserver = 1;
  551.     }
  552.     
  553.     if (bPtr->groupIndex==0) {
  554.     bPtr->groupIndex = ++tagIndex;
  555.     }
  556.     newMember->groupIndex = bPtr->groupIndex;
  557. }
  558.  
  559.  
  560. void
  561. WMSetButtonContinuous(WMButton *bPtr, Bool flag)
  562. {
  563.     bPtr->flags.continuous = flag;
  564.     if (bPtr->timer) {
  565.     WMDeleteTimerHandler(bPtr->timer);
  566.     bPtr->timer = NULL;
  567.     }
  568. }
  569.  
  570.  
  571. void
  572. WMSetButtonPeriodicDelay(WMButton *bPtr, float delay, float interval)
  573. {
  574.     bPtr->periodicInterval = interval;
  575.     bPtr->periodicDelay = delay;
  576. }
  577.  
  578.  
  579.  
  580. static void
  581. paintButton(Button *bPtr)
  582. {
  583.     W_Screen *scrPtr = bPtr->view->screen;
  584.     WMReliefType relief;
  585.     int offset;
  586.     char *caption;
  587.     WMPixmap *image;
  588.     WMColor *textColor;
  589.     GC gc;
  590.  
  591.     gc = NULL;
  592.     caption = bPtr->caption;
  593.  
  594.     if (bPtr->flags.enabled) {
  595.         textColor = (bPtr->textColor!=NULL
  596.                      ? bPtr->textColor : scrPtr->black);
  597.     } else {
  598.         textColor = (bPtr->disTextColor!=NULL
  599.                      ? bPtr->disTextColor : scrPtr->darkGray);
  600.     }
  601.  
  602.     if (bPtr->flags.enabled || !bPtr->dimage)
  603.     image = bPtr->image;
  604.     else
  605.     image = bPtr->dimage;
  606.     offset = 0;
  607.     if (bPtr->flags.bordered)
  608.     relief = WRRaised;
  609.     else
  610.     relief = WRFlat;
  611.  
  612.     if (bPtr->flags.selected) {
  613.         if (bPtr->flags.stateLight) {
  614.             gc = WMColorGC(scrPtr->white);
  615.             textColor = scrPtr->black;
  616.         }
  617.  
  618.     if (bPtr->flags.stateChange) {
  619.         if (bPtr->altCaption)
  620.         caption = bPtr->altCaption;
  621.         if (bPtr->altImage)
  622.         image = bPtr->altImage;
  623.             if (bPtr->altTextColor)
  624.                 textColor = bPtr->altTextColor;
  625.         }
  626.  
  627.     if (bPtr->flags.statePush && bPtr->flags.bordered) {
  628.         relief = WRSunken;
  629.         offset = 1;
  630.     }
  631.     }
  632.  
  633.     if (bPtr->flags.pushed) {
  634.     if (bPtr->flags.pushIn) {
  635.         relief = WRPushed;
  636.         offset = 1;
  637.     }
  638.         if (bPtr->flags.pushLight) {
  639.             gc = WMColorGC(scrPtr->white);
  640.             textColor = scrPtr->black;
  641.         }
  642.  
  643.     if (bPtr->flags.pushChange) {
  644.         if (bPtr->altCaption)
  645.         caption = bPtr->altCaption;
  646.         if (bPtr->altImage)
  647.         image = bPtr->altImage;
  648.             if (bPtr->altTextColor)
  649.                 textColor = bPtr->altTextColor;
  650.     }
  651.     }
  652.  
  653.     W_PaintTextAndImage(bPtr->view, True, WMColorGC(textColor),
  654.             (bPtr->font!=NULL ? bPtr->font : scrPtr->normalFont),
  655.             relief, caption, bPtr->flags.alignment, image, 
  656.             bPtr->flags.imagePosition, gc, offset);
  657. }
  658.  
  659.  
  660.  
  661. static void
  662. handleEvents(XEvent *event, void *data)
  663. {
  664.     Button *bPtr = (Button*)data;
  665.  
  666.     CHECK_CLASS(data, WC_Button);
  667.  
  668.  
  669.     switch (event->type) {
  670.      case Expose:
  671.     if (event->xexpose.count!=0)
  672.         break;
  673.     paintButton(bPtr);
  674.     break;
  675.     
  676.      case DestroyNotify:
  677.     destroyButton(bPtr);
  678.     break;
  679.     }
  680. }
  681.  
  682.  
  683. static void 
  684. autoRepeat(void *data)
  685. {
  686.     Button *bPtr = (Button*)data;
  687.  
  688.     if (bPtr->action && bPtr->flags.pushed)
  689.     (*bPtr->action)(bPtr, bPtr->clientData);
  690.  
  691.     bPtr->timer = WMAddTimerHandler((int)(bPtr->periodicInterval*1000),
  692.                     autoRepeat, bPtr);
  693. }
  694.  
  695.  
  696. static void
  697. handleActionEvents(XEvent *event, void *data)
  698. {
  699.     Button *bPtr = (Button*)data;
  700.     int doclick = 0, dopaint=0;
  701.  
  702.     CHECK_CLASS(data, WC_Button);
  703.  
  704.     if (!bPtr->flags.enabled)
  705.     return;
  706.     
  707.     switch (event->type) {
  708.      case EnterNotify:
  709.     if (bPtr->groupIndex == 0) {
  710.         bPtr->flags.pushed = bPtr->flags.wasPushed;
  711.         if (bPtr->flags.pushed) {
  712.         bPtr->flags.selected = !bPtr->flags.prevSelected;
  713.         dopaint = 1;
  714.         }
  715.     }
  716.     break;
  717.  
  718.      case LeaveNotify:
  719.     if (bPtr->groupIndex == 0) {
  720.         bPtr->flags.wasPushed = bPtr->flags.pushed;
  721.         if (bPtr->flags.pushed) {
  722.         bPtr->flags.selected = bPtr->flags.prevSelected;
  723.         dopaint = 1;
  724.         }
  725.         bPtr->flags.pushed = 0;
  726.     }
  727.     break;
  728.  
  729.      case ButtonPress:
  730.     if (event->xbutton.button == Button1) {
  731.         if (bPtr->groupIndex>0) {
  732.         if (!bPtr->flags.selected)
  733.             doclick = 1;
  734.         bPtr->flags.pushed = 1;
  735.         bPtr->flags.selected = 1;
  736.         dopaint = 1;
  737.         break;
  738.         }
  739.         bPtr->flags.wasPushed = 0;
  740.         bPtr->flags.pushed = 1;
  741.         bPtr->flags.prevSelected = bPtr->flags.selected;
  742.         bPtr->flags.selected = !bPtr->flags.selected;
  743.         dopaint = 1;
  744.         
  745.         if (bPtr->flags.continuous && !bPtr->timer) {
  746.         bPtr->timer = WMAddTimerHandler((int)(bPtr->periodicDelay*1000),
  747.                         autoRepeat, bPtr);
  748.         }
  749.     }
  750.     break;
  751.  
  752.      case ButtonRelease:
  753.     if (event->xbutton.button == Button1) {
  754.         if (bPtr->flags.pushed) {
  755.         if (bPtr->groupIndex==0)
  756.             doclick = 1;
  757.         dopaint = 1;
  758.         if (bPtr->flags.springLoaded) {
  759.             bPtr->flags.selected = bPtr->flags.prevSelected;
  760.         }
  761.         }
  762.         bPtr->flags.pushed = 0;
  763.     }
  764.     if (bPtr->timer) {
  765.         WMDeleteTimerHandler(bPtr->timer);
  766.         bPtr->timer = NULL;
  767.     }
  768.     break;    
  769.     }
  770.  
  771.     if (dopaint)
  772.     paintButton(bPtr);
  773.     
  774.     if (doclick) {
  775.     if (bPtr->flags.selected && bPtr->groupIndex>0) {
  776.         WMPostNotificationName(WMPushedRadioNotification, bPtr, NULL);
  777.     }
  778.     
  779.     if (bPtr->action)
  780.         (*bPtr->action)(bPtr, bPtr->clientData);
  781.     }
  782. }
  783.  
  784.  
  785.  
  786. static void
  787. destroyButton(Button *bPtr)
  788. {
  789.     if (bPtr->flags.addedObserver) {
  790.     WMRemoveNotificationObserver(bPtr);
  791.     }
  792.  
  793.     if (bPtr->timer)
  794.     WMDeleteTimerHandler(bPtr->timer);
  795.     
  796.     if (bPtr->font)
  797.     WMReleaseFont(bPtr->font);
  798.     
  799.     if (bPtr->caption)
  800.     wfree(bPtr->caption);
  801.  
  802.     if (bPtr->altCaption)
  803.     wfree(bPtr->altCaption);
  804.  
  805.     if (bPtr->textColor)
  806.         WMReleaseColor(bPtr->textColor);
  807.  
  808.     if (bPtr->altTextColor)
  809.         WMReleaseColor(bPtr->altTextColor);
  810.  
  811.     if (bPtr->disTextColor)
  812.         WMReleaseColor(bPtr->disTextColor);
  813.  
  814.     if (bPtr->image)
  815.     WMReleasePixmap(bPtr->image);
  816.  
  817.     if (bPtr->dimage) {
  818.     /* yuck.. kluge */
  819.     bPtr->dimage->pixmap = None;
  820.  
  821.     WMReleasePixmap(bPtr->dimage);
  822.     }
  823.     if (bPtr->altImage)
  824.     WMReleasePixmap(bPtr->altImage);
  825.  
  826.     wfree(bPtr);
  827. }
  828.  
  829.  
  830.